//
//  RandomGen.h
//  WormLattice
//
//  Created by Snir Gazit on 12/10/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#ifndef RandomGen_h
#define RandomGen_h
#include <boost/random.hpp>
#include <boost/random/mersenne_twister.hpp>
#include "def.h"

typedef boost::uniform_real<> UniReal;
typedef boost::uniform_real<>::param_type UniRealParams;
typedef boost::uniform_int<> UniInt;
typedef boost::uniform_int<>::param_type UniIntParams;
typedef boost::binomial_distribution<> Binomial;
typedef boost::random::discrete_distribution<> Discrete;
typedef boost::random::discrete_distribution<>::param_type DiscreteParams;
typedef boost::normal_distribution<> NormalDist;
typedef boost::normal_distribution<>::param_type NormalDistParams;
using namespace std;

template<class EnginType>
class GenType {
	EnginType eng_;
public:
	void seed(int seed) {
		eng_.seed(seed);
	}
	void dump(string outPath) const {
		string rndFileName = outPath + "/rndStream.dat";
		ofstream rndFile;
		rndFile.open(rndFileName.c_str());
		rndFile << eng_;
		rndFile.close();
	}
	void read(string outPath) {
		string rndFileName = outPath + "/rndStream.dat";
		ifstream rndFile;
		rndFile.open(rndFileName.c_str());
		rndFile >> eng_;
		rndFile.close();
	}
	const EnginType* getEngine() const {
		return &eng_;
	}
	EnginType* getEngine() {
		return &eng_;
	}
};

template<class GenType, class distType>
class RandomVariable {
public:
	typedef typename distType::result_type result_type;
	typedef typename distType::param_type param_type;
	void init(GenType *eng, param_type param) {
		eng_ = eng;
		setParams(param);
	}
	result_type draw() {
		return dist_(*(eng_->getEngine()));
	}
	void setParams(param_type param) {
		dist_.param(param);
	}
private:
	distType dist_;
	GenType *eng_;
	param_type param_;
};

typedef GenType<boost::mt19937> MTGen;
typedef RandomVariable<MTGen,UniReal> UniformReal;
typedef RandomVariable<MTGen,UniInt> UniformInt;
typedef RandomVariable<MTGen,NormalDist> Normal;

typedef MTGen SimGen;

#endif
